package it.webrules.deploymanager.core.st;

import it.webrules.deploymanager.core.Function;
import it.webrules.deploymanager.core.OperationResult;
import it.webrules.deploymanager.core.config.Command;
import it.webrules.deploymanager.core.config.ConfigurationException;
import it.webrules.deploymanager.core.config.ConfigurationService;
import it.webrules.deploymanager.core.st.scm.SCMConnector;
import it.webrules.deploymanager.core.st.scm.SCMException;
import it.webrules.deploymanager.core.st.scm.SCMService;
import it.webrules.deploymanager.core.st.scm.StaticHookManager;
import it.webrules.deploymanager.core.st.scm.Type;

/**
 * Manage static parts function. 
 * This class is responsible of invoke hook  
 * 
 * @author dometec
 *
 */
public class DeployManagerStatic implements Function {

	public boolean canManage(ConfigurationService configurationService) {
		return configurationService.getStaticConfig() != null;
	}

	public Object start(ConfigurationService configurationService) throws SCMException, ConfigurationException {

		SCMService scmService = new SCMService(configurationService);
		SCMConnector scmConnector = scmService.getScmConnector();
		StaticHookManager hookManager = scmService.getStaticHookManager();

		try {

			hookManager.beforestart();

		} catch (Exception e) {
			throw new SCMException("Before start hook failed!", e);
		}

		Object response;
		Command command = configurationService.getCommand();
		switch (command) {

		case ListDeployableRelease:
			response = scmConnector.getSwitchableDirs();
			break;

		case Info:
			response = scmConnector.info();
			break;

		case Checkout:
			checkType(configurationService);
			if (!configurationService.getType().equals(Type.Trunk))
				checkName(configurationService);
			response = scmConnector.checkout(configurationService.getType(), configurationService.getName(),
					configurationService.getForceCheckout());
			break;

		case Cleanup:
			response = scmConnector.cleanup();
			break;

		case CreateTagOrBranch:
			checkType(configurationService);
			if (configurationService.getType().equals(Type.Trunk))
				throw new ConfigurationException("Type parameter can be Tag or Branch!");

			checkName(configurationService);
			response = createTagOrBranch(scmConnector, configurationService.getSrctype(), configurationService.getSrcname(),
					configurationService.getType(), configurationService.getName(), configurationService.getSwitchin());
			break;

		case StatusFile:
			response = scmConnector.status();
			break;

		case DiffContent:
			response = scmConnector.diff();
			break;

		case Revert:
			response = scmConnector.revert();
			break;

		case Update:
			response = scmConnector.update();
			break;

		case Deploy:
			checkType(configurationService);
			checkName(configurationService);
			response = scmConnector.switchTo(configurationService.getType(), configurationService.getName());
			break;

		case DeleteBranch:
			checkName(configurationService);
			response = scmConnector.delete(Type.Branch, configurationService.getName());
			break;

		case Log:
			response = scmConnector.log();
			break;

		case CreateSimpleGraph:
			response = scmConnector.createSimpleGraph(configurationService.getGraphOutputFile());
			break;

		case CreateCompleteGraph:
			response = scmConnector.createCompleteGraph(configurationService.getGraphOutputFile());
			break;

		case NextDefaultVersions:
			response = scmConnector.getNextTagVersion();
			break;

		case TagTrunkAndDeploy:

			String nextRelease = configurationService.getName();
			if (nextRelease == null || nextRelease.isEmpty())
				nextRelease = scmConnector.getNextTagVersion();

			response = createTagOrBranch(scmConnector, Type.Trunk, null, Type.Tag, nextRelease, true);
			break;

		default:
			response = new OperationResult("Nothing to do, " + command + " is not for Static Parts");
			break;

		}

		try {

			hookManager.afterend();

		} catch (Exception e) {
			throw new SCMException("After end hook failed!", e);
		}

		return response;

	}

	private Object createTagOrBranch(SCMConnector scmConnector, Type srctype, String srcname, Type dsttype, String dstname, Boolean swichin)
			throws ConfigurationException, SCMException {

		if (srctype == null) {
			srctype = Type.Trunk;
		} else if (!srctype.equals(Type.Trunk) && srcname == null) {
			throw new ConfigurationException("Need Name parameter!");
		}

		OperationResult response = scmConnector.copy(srctype, srcname, dsttype, dstname);
		if (response.success && swichin)
			response = scmConnector.switchTo(dsttype, dstname);

		return response;
	}

	private void checkType(ConfigurationService configurationService) throws ConfigurationException {
		if (configurationService.getType() == null)
			throw new ConfigurationException("Need Type parameter!");
	}

	private void checkName(ConfigurationService configurationService) throws ConfigurationException {
		if (configurationService.getName() == null)
			throw new ConfigurationException("Need Name parameter!");
	}

}
